package city.spring.modules.oldman.service.impl;

import city.spring.modules.bed.entity.BedEntity;
import city.spring.modules.bed.service.BedService;
import city.spring.modules.cardinfo.entity.CardNumberEntity;
import city.spring.modules.cardinfo.service.CardNumberService;
import city.spring.modules.checkinfee.entity.CheckinfeeEntity;
import city.spring.modules.checkinfee.repository.CheckinfeeRepository;
import city.spring.modules.checkinfeeDetail.entity.CheckinfeeDetailEntity;
import city.spring.modules.checkinfeeDetail.service.CheckinfeeDetailService;
import city.spring.modules.ext.entity.OldmanDiseaseExtEntity;
import city.spring.modules.ext.service.OldmanDiseaseExtService;
import city.spring.modules.oldman.entity.OldmanAttendanceEntity;
import city.spring.modules.oldman.entity.OldmanBedEntity;
import city.spring.modules.oldman.entity.OldmanFamilydependentEntity;
import city.spring.modules.oldman.entity.OldmanInfoEntity;
import city.spring.modules.oldman.mapstruct.OldmanMapStruct;
import city.spring.modules.oldman.repository.OldmanAttendanceRepository;
import city.spring.modules.oldman.repository.OldmanInfoRepository;
import city.spring.modules.oldman.service.OldmanBedService;
import city.spring.modules.oldman.service.OldmanFamilydependentService;
import city.spring.modules.oldman.service.OldmanInfoService;
import city.spring.modules.oldman.vo.OldmanVO;
import city.spring.modules.reception.entity.AdvisoryEntity;
import city.spring.modules.reception.entity.CheckInRecordEntity;
import city.spring.modules.reception.entity.ReservationEntity;
import city.spring.modules.reception.repository.AdvisoryRepository;
import city.spring.modules.reception.repository.ReservationRepository;
import city.spring.modules.reception.service.CheckInRecordService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * Service：老人信息
 *
 * @author 侯坤林
 * @date 2020-05-23 04:39:16
 */
@CacheConfig(cacheNames = {OldmanInfoServiceImpl.CACHE_NAME})
@Transactional(rollbackFor = Throwable.class)
@Service
public class OldmanInfoServiceImpl extends ServiceImpl<OldmanInfoRepository, OldmanInfoEntity> implements OldmanInfoService {
    private final BedService bedService;
    private final CheckInRecordService checkInRecordService;
    private final CardNumberService cardNumberService;
    private final OldmanInfoRepository oldmanInfoRepository;
    private final OldmanMapStruct oldmanMapStruct;
    private final OldmanDiseaseExtService oldmanDiseaseExtService;
    private final AdvisoryRepository advisoryRepository;
    private final ReservationRepository reservationRepository;
    private final OldmanFamilydependentService oldmanFamilydependentService;
    private final OldmanAttendanceRepository oldmanAttendanceRepository;
    private final OldmanBedService oldmanBedService;
    private final CheckinfeeRepository checkinfeeRepository;
    @Autowired
    CheckinfeeDetailService checkinfeeDetailService;

    public OldmanInfoServiceImpl(BedService bedService, CheckInRecordService checkInRecordService, OldmanInfoRepository oldmanInfoRepository, CardNumberService cardNumberService, OldmanMapStruct oldmanMapStruct, OldmanDiseaseExtService oldmanDiseaseExtService, AdvisoryRepository advisoryRepository, ReservationRepository reservationRepository, OldmanFamilydependentService oldmanFamilydependentService, OldmanAttendanceRepository oldmanAttendanceRepository, OldmanBedService oldmanBedService, CheckinfeeRepository checkinfeeRepository) {
        this.bedService = bedService;
        this.checkInRecordService = checkInRecordService;
        this.oldmanInfoRepository = oldmanInfoRepository;
        this.cardNumberService = cardNumberService;
        this.oldmanMapStruct = oldmanMapStruct;
        this.oldmanDiseaseExtService = oldmanDiseaseExtService;
        this.advisoryRepository = advisoryRepository;
        this.reservationRepository = reservationRepository;
        this.oldmanFamilydependentService = oldmanFamilydependentService;
        this.oldmanAttendanceRepository = oldmanAttendanceRepository;
        this.oldmanBedService = oldmanBedService;
        this.checkinfeeRepository = checkinfeeRepository;
    }

    @Override
    public OldmanVO getOldmanInfo(String id) {
        OldmanInfoEntity entity = getById(id);
        System.out.println("rweuriewop" + entity);
        OldmanVO vo = oldmanMapStruct.toVo(entity);
        // 获取老人关联的既往病史疾病ID列表
        List<OldmanDiseaseExtEntity> diseaseExtEntities = oldmanDiseaseExtService.lambdaQuery()
                .eq(OldmanDiseaseExtEntity::getOldmanId, id)
                .list();
        Set<String> diseaseIds = diseaseExtEntities
                .stream()
                .map(OldmanDiseaseExtEntity::getDiseaseId)
                .collect(Collectors.toSet());
        vo.setPastMedicalHistoryIds(diseaseIds);
        return vo;
    }

    @Override
    public void saveOldmanInfo(OldmanInfoEntity entity) {
        if (!save(entity)) {
            throw new RuntimeException("保存信息失败");
        }
        updateDisease(entity);
    }

    @Override
    public void updateOldmanInfo(OldmanInfoEntity entity) {
        // 使用 updateById(entity); 修改数据时，将会修改 entity 对象中所有非null数据，如果某个字段为null，将会忽略该字段的修改
        Integer oldmanNum = lambdaQuery()
                .eq(OldmanInfoEntity::getCertificate, entity.getCertificate())
                .eq(OldmanInfoEntity::getCertificateType, entity.getCertificateType())
                .ne(OldmanInfoEntity::getId, entity.getId())
                .count();
        if (oldmanNum > 0) {
            throw new RuntimeException("系统中已经存在该老人证件信息");
        }
        boolean update = saveOrUpdate(entity);
        if (!update) {
            throw new RuntimeException("修改信息失败");
        }
        updateDisease(entity);
    }

    /**
     * 修改老人的疾病关联信息
     *
     * @param entity
     */
    private void updateDisease(OldmanInfoEntity entity) {
        if (entity instanceof OldmanVO) {
            OldmanVO vo = (OldmanVO) entity;
            Set<String> pastMedicalHistory = vo.getPastMedicalHistoryIds();
            if (pastMedicalHistory == null || pastMedicalHistory.isEmpty()) {
                return;
            }
            oldmanDiseaseExtService.lambdaUpdate()
                    .in(OldmanDiseaseExtEntity::getDiseaseId, pastMedicalHistory)
                    .remove();
            List<OldmanDiseaseExtEntity> list = new ArrayList<>();
            for (String diseaseId : pastMedicalHistory) {
                list.add(new OldmanDiseaseExtEntity(null, diseaseId, entity.getId()));
            }
            oldmanDiseaseExtService.saveBatch(list);
        }
    }

    @Override
    public void deleteOldmanInfo(String primaryKey) {

        // 删除老人咨询记录
        AdvisoryEntity advisory = advisoryRepository.getAdvisoryByOldmanId(primaryKey);
        if (advisory != null) {
            advisoryRepository.deleteById(advisory.getId());
        }

        // 删除预约记录
        ReservationEntity reservation = reservationRepository.getReservationByOldmanId(primaryKey);
        if (reservation != null) {
            reservationRepository.deleteById(reservation.getId());
        }

        // 删除入住登记信息
        List<CheckInRecordEntity> checkInRecordList = checkInRecordService.getCheckInRecordListByOldmanId(primaryKey);
        System.out.println("checkInRecordList" + checkInRecordList);
        if (!checkInRecordList.isEmpty()) {
            List<String> checkInRecordId = checkInRecordList.stream().map(CheckInRecordEntity::getId).collect(Collectors.toList());
            checkInRecordService.removeByIds(checkInRecordId);
        }

        // 删除家属信息
        List<OldmanFamilydependentEntity> familydependentList = oldmanFamilydependentService.getFamilydependentByOldmanId(primaryKey);
        System.out.println("familydependentList" + familydependentList);
        if (!familydependentList.isEmpty()) {
            List<String> familydependentId = familydependentList.stream().map(OldmanFamilydependentEntity::getId).collect(Collectors.toList());
            oldmanFamilydependentService.removeByIds(familydependentId);
        }

        // 删除护理级别信息
        OldmanAttendanceEntity attendanceInfo = oldmanAttendanceRepository.getAttendanceInfoByoldmanId(primaryKey);
        System.out.println("attendanceInfo" + attendanceInfo);
        if (attendanceInfo != null) {
            oldmanAttendanceRepository.deleteById(attendanceInfo.getId());
        }
        // 删除床位信息
        OldmanBedEntity bedInfo = oldmanBedService.getBedInfoByoldmanId(primaryKey);
        System.out.println("bedInfo" + bedInfo);
        if (bedInfo != null) {
            // 删除老人床位同时设置该床位为空
            BedEntity bedEntity = bedService.getById(bedInfo.getBedId());
            bedEntity.setOldmanId(null);
            bedService.lambdaUpdate()
                    .set(BedEntity::getOldmanId, bedEntity.getOldmanId())
                    .eq(BedEntity::getId, bedEntity.getId())
                    .update();
            oldmanBedService.removeById(bedInfo.getId());
        }

        // 删除入院缴费记录
        CheckinfeeEntity checkfee = checkinfeeRepository.getCheckfeeByolamanId(primaryKey);
        System.out.println("checkfee" + checkfee);
        if (checkfee != null) {
            checkinfeeRepository.deleteById(checkfee.getId());
        }

        // 删除入院缴费明细
        List<CheckinfeeDetailEntity> checkinfeeDetailList = checkinfeeDetailService.getCheckinfeeDetailByOldmanId(primaryKey);
        System.out.println("checkinfeeDetailList" + checkinfeeDetailList);
        if (!checkinfeeDetailList.isEmpty()) {
            List<String> checkinfeeDetailId = checkinfeeDetailList.stream().map(CheckinfeeDetailEntity::getId).collect(Collectors.toList());
            checkinfeeDetailService.removeByIds(checkinfeeDetailId);
        }

        removeById(primaryKey);
    }

    @Override
    public void deleteOldmanInfo(List<String> primaryKeys) {
        removeByIds(primaryKeys);
    }

    /**
     * 查找老人状态为正式入住、试入住的老人
     *
     * @return
     */
    @Override
    public List<OldmanInfoEntity> oldmanInfoByStatus() {
        return oldmanInfoRepository.oldmanInfoByStatus();
    }

    @Override
    public void retreat(String oldmanId) {
        OldmanInfoEntity entity = getById(oldmanId);
        if (entity == null) {
            throw new RuntimeException("未找到入住老人信息");
        }

        // 检查状态
        Integer status = entity.getStatus();
        if (status == null || !(status.equals(1) || status.equals(2))) {
            throw new RuntimeException("老人入住状态错误，该老人不是正式入住、试入住的老人");
        }
        entity.setStatus(3);

        // 检查账单
        CardNumberEntity cardNumber = cardNumberService.getCardNumber(entity.getMemberCard());
        if (cardNumber != null && BigDecimal.ZERO.compareTo(cardNumber.getBalance()) > 0) {
            throw new RuntimeException("当前老人存在未支付费用，请先清缴费用后再退住");
        }

        // 修改入住记录
        checkInRecordService.lambdaUpdate()
                .set(CheckInRecordEntity::getCheckOutTime, new Date())
                .eq(CheckInRecordEntity::getOldmanId, oldmanId)
                .isNull(CheckInRecordEntity::getCheckOutTime)
                .update();

        // 解除床位占用
        bedService.lambdaUpdate()
                .set(BedEntity::getOldmanId, null)
                .eq(BedEntity::getOldmanId, oldmanId)
                .update();

        // 修改当前老人信息的入住状态
        updateById(entity);
    }

    @Override
    public List<OldmanInfoEntity> getBirthList(String datevalue) {
        return oldmanInfoRepository.getBirthList(datevalue);
    }

    @Override
    public List<OldmanVO> getFirstPayOldList() {
        return oldmanInfoRepository.getFirstPayOldList();
    }

    @Override
    public void transferCheckin(String id, OldmanInfoEntity entity) {
        if (entity.getStatus().equals(1)) {
            throw new RuntimeException("该老人已经是正式入住状态！");
        }
        if (entity.getStatus().equals(3)) {
            throw new RuntimeException("该老人已经退住，不允许修改！");
        }
        if (!entity.getStatus().equals(2)) {
            throw new RuntimeException("该老人还不是试入住状态，不允许修改！");
        }
        if (entity.getStatus().equals(2)) {
            entity.setStatus(1);
        }
        oldmanInfoRepository.transferCheckin(id, entity);
    }

    @Override
    public List<OldmanVO> getArrearsOldList() {
        return oldmanInfoRepository.getArrearsOldList();
    }

    @Override
    public OldmanInfoEntity estimateCheckInfo(String id) {
        return baseMapper.estimateCheckInfo(id);
    }

}
